function tokenizer(str) {
	
	function isNumber(char) {
    return /^\d+$/.test(char);
	}

	function isOperator(char) {
		return ['+', '-', '*', '/'].indexOf(char) != -1;
	}

	function isParen(char) {
		return ['(', ')'].indexOf(char) != -1;
	}

	function isTargetChar(char) {
		return isNumber(char) || isOperator(char) || isParen(char) || char == ' ';
	}
	
    var token = '';
    var result = [];

    var status;
    str.split('').forEach((char, index) => {
        if (!isTargetChar(char)) {
            throw new Error();
        }
        if (isNumber(char)) {
            if (status != 'char' && token.length > 0) {
                result.push(token);
                token = char;
            } else {
                token += char;
            }
            status = 'char';
        }
        if (isOperator(char)) {
            if (status != 'op' && token.length > 0) {
                result.push(token);
            }
            token = char;
            status = 'op';
        }
        if (isParen(char)) {
            if (status != 'paren' && token.length > 0) {
                result.push(token);
            }
            token = char;
            status = 'paren';
        }
        if (index == str.length - 1) {
            result.push(token);
        }
    });
    return result;
}




function parser(token) {
    var i = 0;
    function nextWord() {
        return token[i++];
    }

    function Node(type, operator, child) {
        this.type = type;
        this.operator = '';
        this.child = [];
    }

    var word = nextWord();
    var root = new Node('root');
    var p = root;

    if (Expr() && !nextWord()) {
        return root;
    } else {
        return false;
    }

    /**
     * Expr -> Term ExprTail
     **/
    function Expr() {
        var node = new Node('Expr');
        p.child.push(node);
        p = node;
        if (!Term()) {
            return false
        } else {
            p = node;
            return ExprTail();
        }
    }

    /** 
     * ExprTail -> + Term ExprTail
     *          |  - Term ExprTail
     *          |  null
     **/
    function ExprTail() {
        var node = new Node('ExprTail');
        p.child.push(node);
        p = node;
        if (word == '+' || word == '-') {
            p.operator = word;
            word = nextWord();
            if (!Term()) {
                return false;
            } else {
                p = node;
                return ExprTail();
            }
        }
        return true;
    }

    /**
     * Term -> Factor TermTail
     **/
    function Term() {
        var node = new Node('Term');
        p.child.push(node);
        p = node;
        if (!Factor()) {
            return false;
        } else {
            p = node;
            return TermTail();
        }
    }

    /**
     * TermTail -> * Factor TermTail
     *          |  / Factor TermTail
     *          |  null
     **/
    function TermTail() {
        var node = new Node('TermTail');
        p.child.push(node);
        p = node;
        if (word == '*' || word == '/') {
            p.operator = word;
            word = nextWord();
            if (!Factor()) {
                return false;
            } else {
                p = node;
                return TermTail();
            }
        }
        return true;
    }

    /** 
     * Factor -> (Expr)
     *        |  num
     **/
    function Factor() {
        var node = new Node('Factor');
        p.child.push(node);
        p = node;
        if (word == '(') {
            word = nextWord();
            if (!Expr()) {
                return false;
            } else if(word != ')') {
                return false;
            }
            word = nextWord();
            return true;
        } else if (isNumber(word)) {
            p.child.push(word);
            word = nextWord();
            return true;
        }
        return false;
    }

    function isNumber(word) {
        return /^\d+$/.test(word);
    }

}


function transformer(root) {
    return transformExpr(root.child[0]);
}

function transformExpr(Expr) {
    var p = Expr;
    var result = transformTerm(p.child[0]);
    while (p.child[1].child.length > 0) {
        var operator = p.child[1].operator;
        var lastParam = transformTerm(p.child[1].child[0]);
        result = `(${operator} ${result} ${lastParam})`;
        p = p.child[1];
    }
    return result;
}

function transformTerm(Term) {
    var p = Term;
    var result = transformFactor(p.child[0]);
    while (p.child[1].child.length > 0) {
        var operator = p.child[1].operator;
        var lastParam = transformFactor(p.child[1].child[0]);
        result = `(${operator} ${result} ${lastParam})`;
        p = p.child[1];
    }
    return result;
}

function transformFactor(Factor) {
    if (Factor.child[0].type == 'Expr') {
        return transformExpr(Factor.child[0]);
    } else {
        return Factor.child[0]
    }
}